﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System.Data;

namespace ExcelImport.Validators
{
    public class DataProcessPipeline
    {
        private static IList<IDataTableProcessor> _dataTableProcessorGlobal = new List<IDataTableProcessor>();// 1
        private IList<IDataTableProcessor> _dataTableProcessor = new List<IDataTableProcessor>();// 2
        private static IList<IDataRowProcessor> _dataRowProcessorGlobal = new List<IDataRowProcessor>();// 3
        private IList<IDataRowProcessor> _dataRowProcessor = new List<IDataRowProcessor>();// 4
        private static IList<IDataRowProcessor> _dataRowProcessorGlobalAfter = new List<IDataRowProcessor>();// 5
        private IList<IDataTableProcessor> _dataTableProcessorAfter = new List<IDataTableProcessor>();// 6
        private static IList<IDataTableProcessor> _dataTableProcessorGlobalAfter = new List<IDataTableProcessor>();// 7
        static DataProcessPipeline()
        {
            _dataRowProcessorGlobal.Add(new RequiredValidator());
            _dataRowProcessorGlobal.Add(new DataLengthValidator());
            _dataRowProcessorGlobal.Add(new ExcelUniqueValidator());
            _dataRowProcessorGlobal.Add(new ValueMappingProcessor());
        }

        public PipelineContext ValidationContext;

        public DataProcessPipeline(PipelineContext context)
        {
            ValidationContext = context;
        }

        public static void RegisterDataTableProcessorGlobal(IDataTableProcessor processor)
        {
            _dataTableProcessorGlobal.Add(processor);
        }

        public void RegisterDataTableProcessor(IDataTableProcessor processor)
        {
            this._dataTableProcessor.Add(processor);
        }

        public static void RegisterDataRowProcessorGlobal(IDataRowProcessor processor)
        {
            _dataRowProcessorGlobal.Add(processor);
        }

        public void RegisterDataRowProcessor(IDataRowProcessor processor)
        {
            this._dataRowProcessor.Add(processor);
        }

        public static void RegisterDataRowProcessorGlobalAfter(IDataRowProcessor processor)
        {
            _dataRowProcessorGlobalAfter.Add(processor);
        }

        public void RegisterDataTableProcessorAfter(IDataTableProcessor processor)
        {
            this._dataTableProcessorAfter.Add(processor);
        }

        public static void RegisterDataTableProcessorGlobalAfter(IDataTableProcessor processor)
        {
            _dataTableProcessorGlobalAfter.Add(processor);
        }
        public bool Run(DataTable dt)
        {
            foreach (var processor in _dataTableProcessorGlobal.Reverse())
            {
                processor.Run(dt, ValidationContext);
            }

            foreach (var processor in _dataTableProcessor.Reverse())
            {
                processor.Run(dt, ValidationContext);
            }

            for (int i = 1; i < dt.Rows.Count; i++)
            {
                ValidationContext.Index = i;

                DataRow row = dt.Rows[i];

                foreach (var processor in _dataRowProcessorGlobal.Reverse())
                {
                    processor.Run(row, ValidationContext);
                }

                foreach (var processor in this._dataRowProcessor.Reverse())
                {
                    processor.Run(row, ValidationContext);
                }

                foreach (var processor in _dataRowProcessorGlobalAfter.Reverse())
                {
                    processor.Run(row, ValidationContext);
                }
            }

            foreach (var processor in _dataTableProcessorAfter.Reverse())
            {
                processor.Run(dt, ValidationContext);
            }

            foreach (var processor in _dataTableProcessorGlobalAfter.Reverse())
            {
                processor.Run(dt, ValidationContext);
            }

            return !ValidationContext.HasError;
        }
    }
}
